package com.its.common.net.client.impl;

import com.its.common.net.client.BaseClient;
import com.its.common.net.client.config.ClientParams;
import com.its.common.net.client.handler.GenericHeartbeatDetector;
import com.its.common.net.core.handler.TailHandler;
import io.netty.buffer.PooledByteBufAllocator;
import io.netty.channel.*;
import io.netty.channel.socket.DatagramChannel;
import io.netty.channel.socket.DatagramPacket;
import io.netty.channel.socket.nio.NioDatagramChannel;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;
import lombok.extern.slf4j.Slf4j;

/**
 * @Author xiaxp
 * @Date 9/14/22 22:51
 * @Description
 */
@Slf4j
public class UdpClient extends BaseClient<DatagramPacket> {

    public UdpClient(ClientParams clientParams) {
        super(clientParams);
    }

    /**
     * 连接执行的操作
     */
    @Override
    public ChannelFuture doStart(int port) {
        this.bootstrap.group(this.group)
            .channel(NioDatagramChannel.class)
            .option(ChannelOption.SO_SNDBUF, READ_WRITE_BUF_CAP)
            .option(ChannelOption.SO_RCVBUF, READ_WRITE_BUF_CAP)
            .option(ChannelOption.SO_BROADCAST, true)
            .option(ChannelOption.ALLOCATOR, PooledByteBufAllocator.DEFAULT)
            .handler(new LoggingHandler(LogLevel.INFO))
            .handler(new ChannelInitializer<DatagramChannel>() {
                @Override
                protected void initChannel(DatagramChannel ch) throws Exception {
                    ChannelPipeline pipeline = ch.pipeline();
                    if (null != heartbeatDefine && heartbeatDefine.active()
                        && heartbeatDefine.heartbeatInterval() > 0) {
                        pipeline.addLast(defaultEventExecutorGroup,
                            new GenericHeartbeatDetector(UdpClient.this, heartbeatDefine));
                    }
                    handlers.forEach((handler) -> pipeline.addLast(defaultEventExecutorGroup, handler));

                    pipeline.addLast(defaultEventExecutorGroup, new TailHandler());
                }
            });
        ChannelFuture future = this.bootstrap.bind(port);
        return future;
    }

    /**
     * 连接成功后立刻执行的操作
     *
     * @param channel channel
     */
    @Override
    protected void doAfterConnected(Channel channel) {
        log.debug("客户端启动成功了，Override的我可以干事情，举个栗子:");
        log.debug("ByteBuf buf = Unpooled.copiedBuffer(new byte[]{23,23,36,23,23});");
        log.debug("InetSocketAddress addr = new InetSocketAddress({接收端地址},{接收端端口});");
        log.debug("client.sendAsync(new DatagramPacket(buf, addr));");
    }
}
